﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using Web.Model;

namespace Web.HelperClasses
{
	public static class XElementExtensions
	{
		public static XElement NsElement(this XElement element, String elementName)
		{
			return element.Element(element.GetDefaultNamespace() + elementName);
		}

		public static IEnumerable<XElement> NsElements(this XElement element, String elementName)
		{
			return element.Elements(element.GetDefaultNamespace() + elementName);
		}

		public static void NsSetElementValue(this XElement element, String elementName, object value)
		{
			element.SetElementValue(element.GetDefaultNamespace() + elementName, value);
		}

	}

	public static class YandexFotkiExtensions
	{
		public static Photo UploadPhotoWithName(this YandexFotki fotki, Bitmap bitmap, string albumUrl, string photoName)
		{
			var yf = fotki.UploadPhoto(bitmap, albumUrl);
			fotki.ChangeName(yf, photoName);
			return yf;
		}
	}

	public class YandexFotki
	{
        private static YandexFotki Instance { get; set; }

        private YandexFotki()
        {
        }

        public static YandexFotki GetInstance()
        {
            if (Instance == null) Instance = new YandexFotki(new HttpClient());
            return Instance;
        }

		public String GetOrCreateAlbum(String albumName)
		{
			XElement album = GetAlbum(albumName) ?? CreateAlbum(albumName);
			return GetHrefByRel(album, "photos");
        }

		public Photo UploadPhoto(Bitmap bitmap, String albumUrl)
		{
			Bitmap magicBitmap = new Bitmap(bitmap);
			using (var memoryStream = new MemoryStream())
			{
				//todo: определять ImageFormat на основе формата фотки, которую нам загружают
				magicBitmap.Save(memoryStream, ImageFormat.Jpeg);
				return NewPhoto(http.Post(albumUrl, "image/gif", memoryStream.ToArray()));
			}
		}

		public void ChangeName(Photo fotka, String name)
		{
			XElement photo = http.Get(fotka.EditResourceUrl);
			photo.NsSetElementValue("title", name);
			fotka.Title = name;
			http.Put(fotka.EditResourceUrl, "application/atom+xml; charset=utf-8; type=entry", photo.ToString());
		}

		public void ChangeSummary(Photo fotka, String summary)
		{
			XElement photo = http.Get(fotka.EditResourceUrl);
			photo.NsSetElementValue("summary", summary);
			fotka.Title = summary;
			http.Put(fotka.EditResourceUrl, "application/atom+xml; charset=utf-8; type=entry", photo.ToString());
		}

		public void Delete(Photo fotka)
		{
			http.Delete(fotka.EditResourceUrl);
		}

		public YandexFotki(HttpClient http)
		{
			this.http = http;
		}

		private string GetAlbumCollectionUrl()
		{
			XElement rootElement = http.Get("http://api-fotki.yandex.ru/api/users/imaginecup/");

			XNamespace appNamespace = rootElement.GetNamespaceOfPrefix("app") ?? rootElement.GetDefaultNamespace();
			IEnumerable<XElement> tags = rootElement.Element(appNamespace + "workspace").Elements(appNamespace + "collection");
			return tags.First(x => x.Attribute("id").Value == "album-list").Attribute("href").Value;
		}

		private static String GetHrefByRel(XElement element, String relType)
		{
			return element.NsElements("link").First(x => x.Attribute("rel").Value == relType).Attribute("href").Value;
		}

		private Photo NewPhoto(XElement elem)
		{
			var tmpString = elem.NsElement("content").Attribute("src").Value;
			tmpString = tmpString.Substring(0, tmpString.LastIndexOf("_") + 1);

			return new Photo
			       	{
			       		EditResourceUrl = GetHrefByRel(elem, "edit"),
			       		ResourceUrl = GetHrefByRel(elem, "self"),

			       		OriginalSizeUrl = tmpString + "orig",
			       		XlSizeUrl = tmpString + "XL",
			       		Title = elem.NsElement("title").Value
			       	};
		}

		private XElement GetAlbum(String albumName)
		{
			var albumList = GetAlbumList();
			return albumList.FirstOrDefault(x => x.NsElement("title").Value == albumName);
		}

		private XElement CreateAlbum(String albumName)
		{
			var albumCollectionUrl = GetAlbumCollectionUrl();
			XNamespace xNamespace = "http://www.w3.org/2005/Atom";
			var contents = new XElement(xNamespace + "entry", new XElement(xNamespace + "title", albumName), new XElement(xNamespace + "summary"));
			return http.Post(albumCollectionUrl, "application/atom+xml; charset=utf-8; type=entry", contents.ToString());
		}

		private IEnumerable<XElement> GetAlbumList()
		{
			string albumCollectionURL = GetAlbumCollectionUrl();
			XElement serviceDocument = http.Get(albumCollectionURL);
			return serviceDocument.NsElements("entry");
		}

		private readonly HttpClient http;
	}
}